package com.dstats.data;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * Created by MeSeems - Note 1 on 22/01/2015.
 */
public class AppProvider extends ContentProvider {

    private static final int HERO = 100;
    private static final int HERO_ROLE = 101;

    private AtomicInteger mOpenCounter = new AtomicInteger();
    private SQLiteDatabase mDatabase;
    private static DatabaseOpenHelper mDatabaseHelper;


    private static UriMatcher buildUriMatcher() {
        final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
        final String authority = AppDataContract.CONTENT_AUTHORITY;
        matcher.addURI(authority, AppDataContract.PATH_HERO, HERO);
        matcher.addURI(authority, AppDataContract.PATH_HERO_ROLES, HERO_ROLE);
        return matcher;
    }

    private static final UriMatcher sUriMatcher = buildUriMatcher();

    private synchronized SQLiteDatabase openDatabase() {
        if (mOpenCounter.incrementAndGet() == 1) {
            // Opening new database
            mDatabase = getInstance(getContext()).getWritableDatabase();
        }
        return mDatabase;
    }

    private static synchronized DatabaseOpenHelper getInstance(Context context) {
        if (mDatabaseHelper == null) {
            mDatabaseHelper = new DatabaseOpenHelper(context);
        }
        return mDatabaseHelper;
    }

    synchronized void closeDatabase() {
        if (mOpenCounter.decrementAndGet() == 0) {
            // Closing database
            mDatabase.close();
        }
    }

    synchronized public void reset() {
        SQLiteDatabase db = openDatabase();
        //mDatabaseHelper.dropAllTables(db);
        mDatabaseHelper.onCreate(db);
        closeDatabase();
    }

    @Override
    public boolean onCreate() {
        return false;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        final int match = sUriMatcher.match(uri);
        Cursor retCursor;
        switch (match) {
            case HERO: {
                retCursor = openDatabase().query(
                        AppDataContract.AppHeroEntry.TABLE_NAME,
                        projection,
                        selection,
                        selectionArgs,
                        null,
                        null,
                        sortOrder
                );
                break;
            }
            case HERO_ROLE: {
                retCursor = openDatabase().query(
                        AppDataContract.AppHeroRolesEntry.TABLE_NAME,
                        projection,
                        selection,
                        selectionArgs,
                        null,
                        null,
                        sortOrder
                );
                break;
            }
            default:
                throw new UnsupportedOperationException("Unknown uri: " + uri);
        }
        retCursor.setNotificationUri(getContext().getContentResolver(), uri);
        return retCursor;
    }

    @Override
    public String getType(Uri uri) {
        return null;
    }

    @Override
    public Uri insert(Uri uri, ContentValues contentValues) {
        final int match = sUriMatcher.match(uri);
        boolean hasChanged = false;
        SQLiteDatabase db = openDatabase();
        Uri returnUri;

        switch (match) {

            case HERO: {
                long _id = db.insertWithOnConflict(
                        AppDataContract.AppHeroEntry.TABLE_NAME,
                        null,
                        contentValues,
                        SQLiteDatabase.CONFLICT_IGNORE);
                if (_id > 0) {
                    returnUri = AppDataContract.AppHeroEntry.buildUri(_id);
                    hasChanged = true;
                }  else returnUri = uri;
                break;
            }
            case HERO_ROLE: {
                long _id = db.insertWithOnConflict(AppDataContract.AppHeroRolesEntry.TABLE_NAME,
                        null,
                        contentValues,
                        SQLiteDatabase.CONFLICT_REPLACE);
                if (_id > 0) {
                    returnUri = AppDataContract.AppHeroEntry.buildUri(_id);
                    hasChanged = true;
                } else throw new android.database.SQLException("Failed to insert into " + uri);
                break;
            }
            default:
                throw new UnsupportedOperationException("Unknown uri: " + uri);
        }
        if (hasChanged) {
            getContext().getContentResolver().notifyChange(uri, null);
        }
        closeDatabase();
        return returnUri;
    }

    @Override
    public int delete(Uri uri, String s, String[] strings) {
        return 0;
    }

    @Override
    public int update(Uri uri, ContentValues contentValues, String selection, String[] selectionArgs) {
        final int match = sUriMatcher.match(uri);
        SQLiteDatabase db = openDatabase();
        int rowsUpdated = 0;
        switch (match) {
            case HERO: {
                rowsUpdated = db.update(
                        AppDataContract.AppHeroEntry.TABLE_NAME, contentValues, selection, selectionArgs);
                break;
            }
            case HERO_ROLE: {
                rowsUpdated = db.update(
                        AppDataContract.AppHeroRolesEntry.TABLE_NAME, contentValues, selection, selectionArgs);
                break;
            }
            default:
                throw new UnsupportedOperationException("Unknown uri: " + uri);
        }
        if (rowsUpdated>0) {
            getContext().getContentResolver().notifyChange(uri, null);
        }
        closeDatabase();
        return rowsUpdated;
    }
}
